package com.sgj.handler;

import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.sgj.enums.PayTypeEnum;
import com.sgj.utils.QrCodeUtil;
import com.wechat.pay.contrib.apache.httpclient.WechatPayHttpClientBuilder;
import com.wechat.pay.contrib.apache.httpclient.auth.AutoUpdateCertificatesVerifier;
import com.wechat.pay.contrib.apache.httpclient.auth.PrivateKeySigner;
import com.wechat.pay.contrib.apache.httpclient.auth.WechatPay2Credentials;
import com.wechat.pay.contrib.apache.httpclient.auth.WechatPay2Validator;
import com.wechat.pay.contrib.apache.httpclient.util.PemUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.util.EntityUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.math.BigDecimal;
import java.security.PrivateKey;

/**
 * 微信支付（native）
 * @author 沈国纪
 * @date 2022/1/3 15:51
 */
@Slf4j
@Component
public class WxNativeHandler extends AbstractHandler {

	@Value("${wxpay.appid}")
	private String WX_APPID;
	@Value("${wxpay.apiv3PrivateKey}")
	public String WX_APIV3_PRIVATEKEY;
	@Value("${wxpay.privateKey}")
	public String WX_PRIVATEKEY;
	@Value("${wxpay.merchantSerialNumber}")
	public String WX_MERCHANTSERIALNUMBER;
	@Value("${wxpay.mer_id}")
	public String WX_MER_ID;
	@Value("${wxpay.notifyUrl}")
	public String WX_NOTIFY_URL;

	@Override
	public void pay(String orderName, String orderNo, BigDecimal amount, HttpServletResponse response) throws IOException {
		// 通过字符串方式转换证书私钥(此处也可以用文件指定方式处理)
		PrivateKey merchantPrivateKey = PemUtil.loadPrivateKey(new ByteArrayInputStream(WX_PRIVATEKEY.getBytes("utf-8")));

		// 自动更新并获取证书
		AutoUpdateCertificatesVerifier verifier = new AutoUpdateCertificatesVerifier(
				new WechatPay2Credentials(WX_MER_ID, new PrivateKeySigner(WX_MERCHANTSERIALNUMBER, merchantPrivateKey)),
				WX_APIV3_PRIVATEKEY.getBytes("utf-8"));

		WechatPayHttpClientBuilder builder = WechatPayHttpClientBuilder.create()
				.withMerchant(WX_MER_ID, WX_MERCHANTSERIALNUMBER, merchantPrivateKey)
				.withValidator(new WechatPay2Validator(verifier));

		// 通过 WechatPayHttpClientBuilder 构造的 HttpClient，会自动的处理签名和验签
		CloseableHttpClient httpClient= builder.build();
		HttpPost httpPost = new HttpPost("https://api.mch.weixin.qq.com/v3/pay/transactions/native");
		httpPost.addHeader("Accept", "application/json");
		httpPost.addHeader("Content-type","application/json; charset=utf-8");

		ByteArrayOutputStream bos = new ByteArrayOutputStream();
		ObjectMapper objectMapper = new ObjectMapper();

		ObjectNode rootNode = objectMapper.createObjectNode();

		// 传入指定参数，具体根据官方文档
		rootNode.put("mchid", WX_MER_ID)
				.put("appid", WX_APPID)
				.put("description", orderName)
				.put("notify_url", WX_NOTIFY_URL)
				.put("out_trade_no", orderNo);
		rootNode.putObject("amount")
				.put("total", amount)
				.put("currency", "CNY");

		objectMapper.writeValue(bos, rootNode);

		httpPost.setEntity(new StringEntity(bos.toString("UTF-8"), "UTF-8"));
		// 发送请求
		CloseableHttpResponse closeableHttpResponse = httpClient.execute(httpPost);

		String bodyAsString = EntityUtils.toString(closeableHttpResponse.getEntity());
		log.info("[WxNativeHandler][pay] 微信支付请求发送成功:{}", JSONObject.toJSONString(bodyAsString));

		// 解析回调 url
		String codeUrl = JSONObject.parseObject(bodyAsString).getString("code_url");

		// 生成二维码
		QrCodeUtil.createQrCodeByUrl(codeUrl, response);
	}

	@Override
	public void afterPropertiesSet() {
		Factory.register(PayTypeEnum.WX_NATIVE, this);
	}
}